﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;

namespace Brilliant.ORM
{
    /// <summary>
    /// OleDb数据访问对象
    /// </summary>
    public class OleDb : IDataProvider
    {
        private DBTrans dbTrans;

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// 是否开启事务处理
        /// </summary>
        public bool Transaction
        {
            get { return dbTrans == null ? false : true; }
        }

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        public OleDb(string connectionString)
        {
            this.ConnectionString = connectionString;
        }

        /// <summary>
        /// 开启事务
        /// </summary>
        public void BeginTransaction()
        {
            dbTrans = new DBTrans();
            dbTrans.Conn = new OleDbConnection(ConnectionString);
            dbTrans.Conn.Open();
            dbTrans.Cmd = new OleDbCommand();
            dbTrans.Cmd.Connection = dbTrans.Conn;
            dbTrans.Trans = dbTrans.Conn.BeginTransaction();
            dbTrans.Cmd.Transaction = dbTrans.Trans;
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        public void Commit()
        {
            dbTrans.Commit();
            dbTrans.Close();
            dbTrans = null;
        }

        /// <summary>
        /// 回滚事务
        /// </summary>
        public void Rollback()
        {
            dbTrans.Rollback();
            dbTrans.Close();
            dbTrans = null;
        }

        /// <summary>
        /// 返回Command对象
        /// </summary>
        private OleDbCommand PrepareCommand(OleDbConnection conn, string cmdText, CommandType cmdType, IDataParameter[] parameters)
        {
            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
            }
            OleDbCommand cmd = new OleDbCommand(cmdText, conn);
            cmd.CommandType = cmdType;
            if (parameters != null)
            {
                cmd.Parameters.Clear();
                cmd.Parameters.AddRange(parameters);
            }
            return cmd;
        }

        /// <summary>
        /// 执行查询指令返回DataSet对象
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>DataSet对象</returns>
        public DataSet ExecDataSet(SQL sql)
        {
            using (OleDbConnection conn = new OleDbConnection(ConnectionString))
            {
                OleDbCommand cmd = PrepareCommand(conn, sql.CmdText, sql.CmdType, sql.Parameters);
                OleDbDataAdapter da = new OleDbDataAdapter(cmd);
                DataSet ds = new DataSet();
                da.Fill(ds);
                return ds;
            }
        }

        /// <summary>
        /// 执行查询指令返回DataReader对象
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>DataReader对象</returns>
        public IDataReader ExecDataReader(SQL sql)
        {
            OleDbConnection conn = new OleDbConnection(ConnectionString);
            OleDbCommand cmd = PrepareCommand(conn, sql.CmdText, sql.CmdType, sql.Parameters);
            return cmd.ExecuteReader(CommandBehavior.CloseConnection);
        }

        /// <summary>
        /// 执行查询指令返回第一行第一列的值
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>第一行第一列的值</returns>
        public object ExecScalar(SQL sql)
        {
            using (OleDbConnection conn = new OleDbConnection(ConnectionString))
            {
                OleDbCommand cmd = PrepareCommand(conn, sql.CmdText, sql.CmdType, sql.Parameters);
                return cmd.ExecuteScalar();
            }
        }

        /// <summary>
        /// 执行查询指令返回受影响行数
        /// </summary>
        /// <param name="sql">查询指令</param>
        /// <returns>受影响行数</returns>
        public int ExecNonQuerry(SQL sql)
        {
            if (Transaction)
            {
                dbTrans.Cmd.CommandText = sql.CmdText;
                dbTrans.Cmd.CommandType = sql.CmdType;
                if (sql.Parameters != null)
                {
                    dbTrans.Cmd.Parameters.Clear();
                    dbTrans.Cmd.Parameters.AddRange(sql.Parameters);
                }
                return dbTrans.Cmd.ExecuteNonQuery();
            }
            else
            {
                using (OleDbConnection conn = new OleDbConnection(ConnectionString))
                {
                    OleDbCommand cmd = PrepareCommand(conn, sql.CmdText, sql.CmdType, sql.Parameters);
                    return cmd.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// 批量执行查询指令返回受影响行数(事务)
        /// </summary>
        /// <param name="sqlList">查询指令列表</param>
        /// <returns>受影响行数</returns>
        public int ExecTrans(List<SQL> sqlList)
        {
            int count = 0;
            try
            {
                BeginTransaction();
                foreach (SQL sql in sqlList)
                {
                    count += ExecNonQuerry(sql);
                }
                Commit();
            }
            catch
            {
                Rollback();
                count = 0;
            }
            return count;
        }

        /// <summary>
        /// 返回一个新的DataParameter对象实例
        /// </summary>
        /// <param name="parameterName">参数名称</param>
        /// <param name="value">参数值</param>
        /// <returns>DataParameter对象</returns>
        public IDataParameter GetParameter(string parameterName, object value)
        {
            OleDbParameter parameter = new OleDbParameter();
            parameter.ParameterName = parameterName;
            parameter.Value = TypeMap.FilterNull(value);
            return parameter;
        }
    }
}
